#include "campus_club_info_manager.h"
#include "../log/campus_logger.h"
#include "campus_club_info_define.h"
#include"../login/campus_login_administer.h"


CampusClubInfoManager::CampusClubInfoManager(CampusWholeServer * whole_server, CampusSqlConnector * sql_connector):
    whole_server_(whole_server),
    sql_connector_(sql_connector)
{
     if (whole_server_ == nullptr || sql_connector_ == nullptr) {
        CampusLogger::warn("CampusLoginManager init fail: dependency is null");
    }

}

CampusClubInfoManager::~CampusClubInfoManager()
{

}


void CampusClubInfoManager::handleClubCreate(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusLogger::info("CampusClubInfoManager::handleClubCreate");

    doSelectClub(hdl, JMsg);
}

void CampusClubInfoManager::handleClubSearch(websocketpp::connection_hdl hdl, json JMsg)    
{
    CampusLogger::info("CampusClubInfoManager::handleClubSearch");

    doSelectSearch(hdl, JMsg);
}

void CampusClubInfoManager::onSelectSucess(std::vector<std::vector<std::pair<std::string, std::string>>>& result, CampusSqlInfo* userData)
{
    CampusClubInfo* p_info_ = dynamic_cast<CampusClubInfo*>(userData);
    std::shared_ptr<CampusClubInfo> p_info(p_info_); // 智能指针管理内存，避免泄漏
    switch (p_info->type)
    {
    case CLUB_SQL_SELECT_CREATE_CLUB:
        handleClubCreateSelected(result, p_info);
        break;
    case CLUB_SQL_SELECT_SEARCH_CLUB:
        handleClubSearchSelected(result, p_info);
        break;
    case CLUB_SQL_SELECT_JOIN_CLUB:
        handleClubJoinSelected(result, p_info);
        break;
    case CLUB_SQL_SELECT_CLUB_GROUP:
        handleClubGroupSelected(result, p_info);
        break;
        case CLUB_SQL_SELECT_CLUB_INFO:
        handleClubInfoSelected(result, p_info);
        break;
    case CLUB_SQL_SELECT_GROUP_CHAT:
        handleClubChatSelected(result, p_info);
        break;
    default:
        break;
    }
}

void CampusClubInfoManager::handleGroupChat(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusLogger::info("handleGroupChat::handleClubChat");
    doSelectChat(hdl,JMsg);
}

void CampusClubInfoManager::onSelectFail(CampusSqlInfo* p_info_)
{
    std::shared_ptr<CampusClubInfo> p_info(dynamic_cast<CampusClubInfo*>(p_info_)); // 智能指针管理内存，避免泄漏
    
    CampusLogger::warn("CampusClubInfoManager::onSelectClubFail");
}  
 

void CampusClubInfoManager::onInsertSucess(CampusSqlInfo* p_info_)
{
    std::shared_ptr<CampusClubInfo> p_info(dynamic_cast<CampusClubInfo*>(p_info_)); // 智能指针管理内存，避免泄漏
    switch (p_info->type)
    {
    case CLUB_SQL_INSERT_CREATE_CLUB:
        handleClubCreateInserted(p_info);
        break;
    case CLUB_SQL_INSERT_JOIN_CLUB:
        handleClubJoinInserted(p_info);
        break;
    default:
        break;
    }
}
void CampusClubInfoManager::onInsertFail(CampusSqlInfo* userData)
{
    CampusClubInfo* p_info_ = dynamic_cast<CampusClubInfo*>(userData);
    std::shared_ptr<CampusClubInfo> p_info(p_info_); // 智能指针管理内存，避免泄漏

    CampusLogger::warn("CampusClubInfoManager::onInsertClubFail");
}

void CampusClubInfoManager::onUpdateSucess(CampusSqlInfo *userData)
{
    CampusLogger::info("CampusClubInfoManager::onUpdateClubSucess");
    std::shared_ptr<CampusClubInfo> p_info(dynamic_cast<CampusClubInfo*>(userData)); // 智能指针管理内存，避免泄漏

}
void CampusClubInfoManager::onUpdateFail(CampusSqlInfo *userData)
{
    CampusLogger::warn("CampusClubInfoManager::onUpdateClubFail");
    std::shared_ptr<CampusClubInfo> p_info(dynamic_cast<CampusClubInfo*>(userData)); // 智能指针管理内存，避免泄漏
}

void CampusClubInfoManager::doSelectClub(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusClubInfo* p_info_ = new CampusClubInfo();
    try{
        p_info_->sql = "SELECT * FROM club_info_t WHERE club_name = ?";

        p_info_->type = CampusClubSqlType::CLUB_SQL_SELECT_CREATE_CLUB;

        p_info_->uid = JMsg["uid"];
        p_info_->club_name = JMsg["club_name"];
        p_info_->student_name = JMsg["student_name"];
        p_info_->student_id = JMsg["student_id"];
        p_info_->class_ = JMsg["class"];
        p_info_->major = JMsg["major"];
        p_info_->college = JMsg["college"];
        p_info_->teacher_name = JMsg["teacher_name"];
        p_info_->teacher_tel = JMsg["teacher_tel"];
        p_info_->hdl = hdl;

        std::vector<std::string>params = {p_info_->club_name};

        sql_connector_->exec(p_info_->sql,SELECT,params,static_cast<void*>(p_info_));
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::doSelectClub fail");
    }
}

void CampusClubInfoManager::doSelectSearch(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusClubInfo* p_info_ = new CampusClubInfo();
    try{
        p_info_->sql = "SELECT * FROM club_info_t WHERE club_name LIKE ?";

        p_info_->type = CampusClubSqlType::CLUB_SQL_SELECT_SEARCH_CLUB;

        p_info_->club_name = JMsg["club_name"];
        p_info_->hdl = hdl;

        std::vector<std::string>params = {std::string("%" + p_info_->club_name + "%")};

        sql_connector_->exec(p_info_->sql,SELECT,params,static_cast<void*>(p_info_));
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::doSelectSearch fail");
    }
}

void CampusClubInfoManager::doSelectJoin(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusClubInfo* p_info_ = new CampusClubInfo();
    try{
        p_info_->sql = "SELECT * FROM club_group_t WHERE club_name = ? AND uid = ?";

        p_info_->type = CampusClubSqlType::CLUB_SQL_SELECT_JOIN_CLUB;

        p_info_->uid = JMsg["uid"];
        p_info_->club_name = JMsg["club_name"];
        p_info_->hdl = hdl;

        std::vector<std::string>params = {p_info_->club_name,p_info_->uid};
        sql_connector_->exec(p_info_->sql,SELECT,params,static_cast<void*>(p_info_));
    }   
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::doSelectJoin fail");
    }
}

void CampusClubInfoManager::doSelectChat(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusClubInfo* p_info_ = new CampusClubInfo();
    try{
        p_info_->sql = "SELECT uid FROM club_group_t WHERE club_name = ?";
        
        p_info_->type = CampusClubSqlType::CLUB_SQL_SELECT_GROUP_CHAT;
        p_info_->uid = JMsg["uid"];
        p_info_->chat_info = JMsg["chat_info"];
        p_info_->club_name = JMsg["club_name"];
        p_info_->hdl = hdl;
        p_info_->chat_serial = JMsg["chat_serial"];

        std::vector<std::string>params = {p_info_->club_name};
        sql_connector_->exec(p_info_->sql,SELECT,params,static_cast<void*>(p_info_));
    }   
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::doSelectChat fail");
    }

}

void CampusClubInfoManager::doClubExist(std::shared_ptr<CampusClubInfo> p_info)
{
    json JMsg;
    try{
        CampusLogger::info("CampusClubInfoManager::onClubCreateSelected exist");
        JMsg["cmd"] = SIGNAL_TYPE_RESP_CREATE_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_CREATE_RET_EXIST;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::onClubCreateSelected fail");

        JMsg["cmd"] = SIGNAL_TYPE_RESP_CREATE_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_CREATE_RET_FAIL;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
}

void CampusClubInfoManager::doInsertClubInfo(std::shared_ptr<CampusClubInfo> p_info)
{
    CampusLogger::info("CampusClubInfoManager::doInsertClubInfo");
    
    CampusClubInfo* p_info2 = new CampusClubInfo(*p_info);
    p_info2->type = CampusClubSqlType::CLUB_SQL_INSERT_CREATE_CLUB;
    p_info2->sql = "INSERT INTO club_info_t (uid,club_name, student_name, student_id, class, major, college, teacher_name, teacher_tel) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";

    std::vector<std::string>params = {p_info2->uid,p_info2->club_name, p_info2->student_name, p_info2->student_id, 
        p_info2->class_, p_info2->major, p_info2->college, p_info2->teacher_name, p_info2->teacher_tel};

    sql_connector_->exec(p_info2->sql,INSERT,params,static_cast<void*>(p_info2));
}

void CampusClubInfoManager::doJoinExist(std::shared_ptr<CampusClubInfo> p_info)
{
    json JMsg;
    try{
        CampusLogger::info("CampusClubInfoManager::onClubJoinSelected exist");
        JMsg["cmd"] = SIGNAL_TYPE_RESP_JOIN_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_JOIN_RET_EXIST;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::onClubJoinSelected fail");

        JMsg["cmd"] = SIGNAL_TYPE_RESP_JOIN_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_JOIN_RET_FAIL;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
}

void CampusClubInfoManager::doInsertClubJoin(std::shared_ptr<CampusClubInfo> p_info)
{
    CampusLogger::info("CampusClubInfoManager::doJoinInsert");

    CampusClubInfo* p_info2 = new CampusClubInfo(*p_info);
    p_info2->type = CampusClubSqlType::CLUB_SQL_INSERT_JOIN_CLUB;
    p_info2->sql = "INSERT INTO club_group_t (club_name, uid) VALUES (?, ?)";

    std::vector<std::string>params = {p_info2->club_name, p_info2->uid};

    sql_connector_->exec(p_info2->sql,INSERT,params,static_cast<void*>(p_info2));
}

void CampusClubInfoManager::doSelectClubInfo(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusClubInfo* p_info_ = new CampusClubInfo();
    try{
        p_info_->sql = "SELECT club_name FROM club_group_t WHERE uid = ?";

        p_info_->type = CampusClubSqlType::CLUB_SQL_SELECT_CLUB_INFO;
        p_info_->uid = JMsg["uid"];
        p_info_->hdl = hdl;

        std::vector<std::string>params = {p_info_->uid};

        sql_connector_->exec(p_info_->sql,SELECT,params,static_cast<void*>(p_info_));
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::doSelectClubInfo fail");
    }

}

void CampusClubInfoManager::doSelectClubGroup(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusClubInfo* p_info_ = new CampusClubInfo();
    try{
        p_info_->sql = "SELECT uid FROM club_group_t WHERE club_name = ?";

        p_info_->type = CampusClubSqlType::CLUB_SQL_SELECT_CLUB_GROUP;
        p_info_->club_name = JMsg["club_name"];
        p_info_->hdl = hdl;

        std::vector<std::string>params = {p_info_->club_name};

        sql_connector_->exec(p_info_->sql,SELECT,params,static_cast<void*>(p_info_));
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::doSelectGroup fail");
    }
}

void CampusClubInfoManager::doSendChatInfo(std::string const &info,std::vector<std::string>const& uid_list,std::string const& sender_uid,std::string const& club_name,int serial)
{
    CampusLogger::info("CampusClubInfoManager::doSendChatInfo");
    
    json JMsg;
    auto online_map = CampusLoginAdminister::GetOnlineMap();
    
    try{
        JMsg["cmd"] = SIGNAL_TYPE_RESP_GROUP_CHAT;
        JMsg["ret"] = CampusClubRet::CLUB_GROUP_CHAT_RET_SUCESS;
        JMsg["chat_serial"] = serial;
        JMsg["chat_info"] = info;
        JMsg["club_name"] = club_name;
        JMsg["uid"] = sender_uid;

        for(std::string const &uid: uid_list){
            if(online_map.count(uid)){
                auto hdl = online_map[uid];
                whole_server_->send(hdl,JMsg.dump());
                CampusLogger::info("CampusClubInfoManager::doSendChatInfo sender uid: {} receiver uid:{} club_name: {}",sender_uid,uid,club_name);
            }

        }
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::doSendChatInfo json failed!");
    }

}

void CampusClubInfoManager::handleClubCreateSelected(std::vector<std::vector<std::pair<std::string, std::string>>> &result, std::shared_ptr<CampusClubInfo> p_info)
{
    CampusLogger::info("CampusClubInfoManager::handleClubCreateSelected");
    if(result.empty()){ //不存在就创建
        doInsertClubInfo(p_info);
    }
    else{
        doClubExist(p_info); //存在就返回存在
    }
}

void CampusClubInfoManager::handleClubCreateInserted(std::shared_ptr<CampusClubInfo> p_info)
{
    CampusLogger::info("CampusClubInfoManager::handleClubCreateInserted");
    json JMsg;
    try{
        CampusLogger::info("CampusClubInfoManager::handleClubCreateInserted");
        JMsg["cmd"] = SIGNAL_TYPE_RESP_CREATE_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_CREATE_RET_SUCESS;
        whole_server_->send(p_info->hdl,JMsg.dump());

        doInsertClubJoin(p_info);
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::handleClubCreateInserted fail");

        JMsg["cmd"] = SIGNAL_TYPE_RESP_CREATE_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_CREATE_RET_FAIL;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
}

void CampusClubInfoManager::handleClubSearchSelected(std::vector<std::vector<std::pair<std::string, std::string>>> &result, std::shared_ptr<CampusClubInfo> p_info)
{
    CampusLogger::info("CampusClubInfoManager::handleClubSearchSelected");
    json JMsg;
    try{
        JMsg["cmd"] = SIGNAL_TYPE_RESP_SEARCH_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_SEARCH_RET_SUCESS;
        JMsg["club_list"] = result;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::handleClubSearchSelected fail");

        JMsg["cmd"] = SIGNAL_TYPE_RESP_SEARCH_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_SEARCH_RET_FAIL;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
}

void CampusClubInfoManager::handleClubJoinSelected(std::vector<std::vector<std::pair<std::string, std::string>>> &result, std::shared_ptr<CampusClubInfo> p_info)
{
    if(result.empty()){ //不存在就加入
        doInsertClubJoin(p_info);
    }
    else{
        doJoinExist(p_info); //存在就返回存在
    }
}

void CampusClubInfoManager::handleClubJoinInserted(std::shared_ptr<CampusClubInfo> p_info)
{
    CampusLogger::info("CampusClubInfoManager::handleClubJoinInserted");
    json JMsg;
    try{
        CampusLogger::info("CampusClubInfoManager::handleClubJoinInserted");
        JMsg["cmd"] = SIGNAL_TYPE_RESP_JOIN_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_JOIN_RET_SUCESS;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
    catch(...){
        CampusLogger::warn("CampusClubInfoManager::handleClubJoinInserted fail");

        JMsg["cmd"] = SIGNAL_TYPE_RESP_JOIN_CLUB;
        JMsg["ret"] = CampusClubRet::CLUB_JOIN_RET_FAIL;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
}

void CampusClubInfoManager::handleClubGroupSelected(std::vector<std::vector<std::pair<std::string, std::string>>> &result, std::shared_ptr<CampusClubInfo> p_info)
{
    //返回所有的成员uid
    try{
        json JMsg;
        JMsg["cmd"] = SIGNAL_TYPE_RESP_GROUP_INFO;
        JMsg["ret"] = CampusClubRet::CLUB_GROUP_RET_SUCESS;

        std::vector<std::string>group_list;
        for(auto& item_list:result){
            for(auto& [key,value]:item_list){
                if(key == "uid"){
                    group_list.push_back(value);
                }
            }
        }
        JMsg["club_name"] = p_info->club_name;
        JMsg["group_list"] = group_list;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }catch(...){
        json JMsg;
        JMsg["ret"] = CampusClubRet::CLUB_GROUP_RET_FAIL;
        whole_server_->send(p_info->hdl,JMsg.dump());

        CampusLogger::warn("CampusClubInfoManager::handleClubGroupSelected fail");
    }
}

void CampusClubInfoManager::handleClubInfoSelected(std::vector<std::vector<std::pair<std::string, std::string>>> &result, std::shared_ptr<CampusClubInfo> p_info)
{
    try{
        json JMsg;
        JMsg["cmd"] = SIGNAL_TYPE_RESP_CLUB_INFO;
        JMsg["ret"] = CampusClubRet::CLUB_INFO_RET_SUCESS;

        std::vector<std::string>club_list;
        for(auto& item_list:result){
            for(auto& [key,value]:item_list){
                if(key == "club_name"){
                    club_list.push_back(value);
                }
            }
        }

        JMsg["club_list"] = club_list;
        whole_server_->send(p_info->hdl,JMsg.dump());
    }
    catch(...){
        json JMsg;
        JMsg["ret"] = CampusClubRet::CLUB_INFO_RET_SUCESS;
        whole_server_->send(p_info->hdl,JMsg.dump());

        CampusLogger::warn("CampusClubInfoManager::handleClubInfoSelected fail");
    }
}

void CampusClubInfoManager::handleClubChatSelected(std::vector<std::vector<std::pair<std::string, std::string>>> &result, std::shared_ptr<CampusClubInfo> p_info)
{
    try{
        std::vector<std::string>uid_list;
        for(auto& item_list:result){
            for(auto& [key,value]:item_list){
                if(key == "uid"){
                    uid_list.push_back(value);
                }
            }
        }
        doSendChatInfo(p_info->chat_info,uid_list,p_info->uid,p_info->club_name,p_info->chat_serial);
    }
    catch(...){
        json JMsg;
        JMsg["ret"] = CampusClubRet::CLUB_GROUP_CHAT_RET_FAIL;
        whole_server_->send(p_info->hdl,JMsg.dump());

        CampusLogger::warn("CampusClubInfoManager::handleClubChatSelected fail");
    }
}

void CampusClubInfoManager::handleClubJoin(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusLogger::info("CampusClubInfoManager::handleClubJoin");

    doSelectJoin(hdl,JMsg);
}

void CampusClubInfoManager::handleClubGroup(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusLogger::info("CampusClubInfoManager::handleClubGroup");

    doSelectClubGroup(hdl,JMsg);

}

void CampusClubInfoManager::handleClubInfo(websocketpp::connection_hdl hdl, json JMsg)
{
    CampusLogger::info("CampusClubInfoManager::handleClubInfo");

    doSelectClubInfo(hdl,JMsg);
}